using System;
using System.Text;
using System.Text.RegularExpressions;

namespace Nextensions.Text
{
	public static class TextTools
	{
        private static readonly Regex _reLine = new Regex(@"\r\n", RegexOptions.Compiled);

		public static string NameFromPath(string Path)
		{
			return Regex.Match(Path, @"\\([^\\]+)$").Groups[1].Value;
		}
		
		public static string NameFromDotPath(string Path)
		{
			return Regex.Match(Path, @"\.([^\.]+)$").Groups[1].Value;
		}

        public static string GetSurroundingTextLine(string Text, int Index, out int IndexInLine)
        {
            char c;
            if ((c = Text[Index]) == '\r' || c == '\n')
            {
                IndexInLine = -1;
                return null;
            }

            int start = Index;
            int end   = Index;

            while (start > 0 && Text[start-1] != '\n')
                start--;

            while (end < Text.Length - 1 && (c = Text[end + 1]) != '\r' && c != '\n')
            {
                //System.Diagnostics.Debug.Write(char.GetNumericValue(Text[end + 1]));
                end++;
            }

            IndexInLine = Index - start;
            return Text.Substring(start, end - start + 1);
        }

        public static int CalculateLineNumber(string Text, int Position)
        {
            return _reLine.Matches(Text.Substring(0, Position)).Count + 1;
        }

        public static int CalculateLineNumber2(string Text, int Position)
        {
            int cur     = 0;
            int line    = 0;

            while (cur < Position && cur > -1)
            {
                cur = Text.IndexOf('\n', cur + 1);
                line++;
            }

            return line;
        }

        public static string ToBinary(byte num)
        {
            return ToBinary(BitConverter.GetBytes(num));
        }

        public static string ToBinary(short num)
        {
            return ToBinary(BitConverter.GetBytes(num));
        }

        public static string ToBinary(ushort num)
        {
            return ToBinary(BitConverter.GetBytes(num));
        }

        public static string ToBinary(int num)
        {
            return ToBinary(BitConverter.GetBytes(num));
        }

        public static string ToBinary(uint num)
        {
            return ToBinary(BitConverter.GetBytes(num));
        }

        public static string ToBinary(long num)
        {
            return ToBinary(BitConverter.GetBytes(num));
        }

        public static string ToBinary(ulong num)
        {
            return ToBinary(BitConverter.GetBytes(num));
        }

        public static string ToBinary(double num)
        {
            return ToBinary(BitConverter.GetBytes(num));
        }

        public static string ToBinary(float num)
        {
            return ToBinary(BitConverter.GetBytes(num));
        }

        public static string ToBinary(bool b)
        {
            return ToBinary(BitConverter.GetBytes(b));
        }

        public static string ToBinary(byte[] buf)
        {
            int byteSize = sizeof(byte) * 8;
            StringBuilder result = new StringBuilder(byteSize * buf.Length);

            for (int byt = buf.Length - 1; byt >= 0; byt--)
            {
                for (int bit = byteSize - 1; bit >= 0; bit--)
                {
                    ulong shift = 1UL << bit;
                    result.Append((buf[byt] & shift) == shift ? "1" : "0");
                }
            }

            return result.ToString();
        }

        public static string GetDurationString(TimeSpan span)
        {
            if (span.TotalSeconds <= 60)
                return String.Format("{0:0.0} seconds", span.TotalSeconds);

            if (span.TotalMinutes <= 60)
                return String.Format("{0} minute{2}, {1} seconds", span.Minutes, span.Seconds, span.Minutes > 1 ? "s" : "");

            if (span.TotalHours <= 24)
                return String.Format("{0} hour{2}, {1} minutes", span.Hours, span.Minutes, span.Hours > 1 ? "s" : "");

            if(span.TotalDays < 365)
                return String.Format("{0} day{2}, {1} hours", span.Days, span.Hours, span.Days > 1 ? "s" : "");

            int years = span.Days / 365;
            int days = span.Days % 365;
            return String.Format("{0} year{2}, {1} days", years, days, years > 1 ? "s" : "");
        }
    }
}